﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;
using Petra.Gis.Geometry;
using Petra.Gis.Geometry.Support;
using Petra.Gis.DataServices.WKT.Support;

namespace Petra.Gis.DataServices.WKT
{


  public partial class RegexGeometryParser
  {

    private static Dictionary<WKTGeometryType, Regex> getValidationRegex;
    private static Dictionary<WKTGeometryType, Regex> getFastRegex;


    private static void prepareRegexExpressions() 
    {

      string pattern;

      Regex.CacheSize = 100;
      RegexOptions rgOpt = RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.CultureInvariant | RegexOptions.ExplicitCapture;

      //init geometry name regex...
      string sep = "";
      pattern = @"(?<geometryname>^[w]*";
      //foreach (KeyValuePair<WKTGeometryType, string> kvp in getWktName)
      foreach (WKTGeometryType kvp in ImplementedTypes)
      {
        pattern += sep + kvp.ToString();
        //pattern = @"^[w]*" + kvp.Value;
        sep = "|";
      }
      pattern += ")";

      _geomNameRgx = new Regex(pattern, RegexOptions.Compiled);

      //init geometry regexes...
      getValidationRegex = new Dictionary<WKTGeometryType, Regex>();
      getFastRegex = new Dictionary<WKTGeometryType, Regex>();



      //Point regex pattern
      pattern = @"(?<whitespace>\s*)" +
        @"(?<geometryname>" + WKTGeometryType.Point.ToString() + ")" + //5-18 chars
        @"(?<geometry>\s*\()" + //cordlist
        @"(?<coordlist>(\s*|\s+)\-?(\d*\.?\d+|\d+\.?\d*)([eE][+-]?\d+)?){2}" +
        @"(?<geometry>\s*\))"; //+ //cordlist end

      getValidationRegex.Add(WKTGeometryType.Point, new Regex(pattern, rgOpt));

      pattern = @"(" + WKTGeometryType.Point.ToString() + ")" +
        @"(\()" +
        @"(?<coordlist>(\s?)\-?(\d*\.?\d+|\d+\.?\d*)([eE][+-]?\d+)?){2}" +
        @"(\))";

      getFastRegex.Add(WKTGeometryType.Point, new Regex(pattern, rgOpt));



      //LineString regex pattern
      pattern = @"(?<whitespace>\s*)" +
        @"(?<geometryname>" + WKTGeometryType.LineString.ToString() + ")" +
        @"(?<geometry>\s*\()" +
        //@"(?<coordlist>(\s*|\s*\,{1}\s*|\s+)\-?(\d*\.?\d+|\d+\.?\d*)([eE][+-]?\d+)?)+" +
        @"((?<separator>\s*|\s*\,{1}\s*|\s+)(?<coordlist>(\-?\d*\.?\d+|\d+\.?\d*)([eE][+-]?\d+)?))+" +
        @"(?<geometry>\s*\))";

      getValidationRegex.Add(WKTGeometryType.LineString, new Regex(pattern, rgOpt));

      pattern = @"(" + WKTGeometryType.LineString.ToString() + ")" +
        @"(\()" +
        @"((\,?\s?)(?<coordlist>(\-?\d*\.?\d+|\d+\.?\d*)([eE][+-]?\d+)?))+" +
        @"(\))";

      getFastRegex.Add(WKTGeometryType.LineString, new Regex(pattern, rgOpt));



      //Polygon regex pattern
      pattern = @"(?<whitespace>\s*)" +
        @"(?<geometryname>" + WKTGeometryType.Polygon.ToString() + ")" +
        @"(?<geometry>\s*\()" +
        @"((?<rseparator>\s*|\s*\,{1}\s*|\s+)(?<geometry1>\()" +
        //@"(?<coordlist>(\s*|\s*\,{1}\s*|\s+)\-?(\d*\.?\d+|\d+\.?\d*)([eE][+-]?\d+)?)+" +
        @"((?<separator>\s*|\s*\,{1}\s*|\s+)(?<coordlist>(\-?\d*\.?\d+|\d+\.?\d*)([eE][+-]?\d+)?))+" +
        @"(?<geometry1>\s*\)))+" +
        @"(?<geometry>\s*\))";

      getValidationRegex.Add(WKTGeometryType.Polygon, new Regex(pattern, rgOpt));

      pattern = @"(" + WKTGeometryType.Polygon.ToString() + ")" +
        @"(?<geometry>\()" +
        @"((\,?)(?<geometry1>\()" +
        @"((\,?\s?)(?<coordlist>(\-?\d*\.?\d+|\d+\.?\d*)([eE][+-]?\d+)?))+" +
        @"(?<geometry1>\)))+" +
        @"(?<geometry>\))";

      getFastRegex.Add(WKTGeometryType.Polygon, new Regex(pattern, rgOpt));



      //MultiPoint regex pattern
      pattern = @"(?<whitespace>\s*)" +
        @"(?<geometryname>" + WKTGeometryType.MultiPoint.ToString() + ")" +
        @"(?<geometry>\s*\({1})" +
        //@"(?<coordlist>(\s*|\s*\,{1}\s*|\s+)\-?(\d*\.?\d+|\d+\.?\d*)([eE][+-]?\d+)?)+" +
        @"((?<separator>\s*|\s*\,{1}\s*|\s+)(?<coordlist>(\-?\d*\.?\d+|\d+\.?\d*)([eE][+-]?\d+)?))+" +
        @"(?<geometry>\s*\){1})"; //+
      //@"(?<invalid>[^\s]+)"; //put all regex exps here to avoid invalid chars in input string

      getValidationRegex.Add(WKTGeometryType.MultiPoint, new Regex(pattern, rgOpt));
      getFastRegex.Add(WKTGeometryType.MultiPoint, getValidationRegex[WKTGeometryType.MultiPoint]);
      


      //MultiLine regex pattern
      pattern = @"(?<whitespace>\s*)" +
        @"(?<geometryname>" + WKTGeometryType.MultiLineString.ToString() + ")" +
        @"(?<geometry>\s*\()" +
        @"((?<sseparator>\s*|\s*\,{1}\s*|\s+)(?<geometry1>\()" +
        //@"(?<coordlist>(\s*|\s*\,{1}\s*|\s+)\-?(\d*\.?\d+|\d+\.?\d*)([eE][+-]?\d+)?)+" +
        @"((?<separator>\s*|\s*\,{1}\s*|\s+)(?<coordlist>(\-?\d*\.?\d+|\d+\.?\d*)([eE][+-]?\d+)?))+" +
        @"(?<geometry1>\s*\)))+" +
        @"(?<geometry>\s*\))"; // +
        //@"(?<invalid>[^\s]+)"; //put all regex exps here to avoid invalid chars in input string

      getValidationRegex.Add(WKTGeometryType.MultiLineString, new Regex(pattern, rgOpt));
      getFastRegex.Add(WKTGeometryType.MultiLineString, getValidationRegex[WKTGeometryType.MultiLineString]);



      //MultiPolygon regex pattern
      pattern = @"(?<whitespace>\s*)" +
        @"(?<geometryname>" + WKTGeometryType.MultiPolygon.ToString() + ")" +
        @"(?<geometry>\s*\()" +
        @"((?<pseparator>\s*|\s*\,{1}\s*|\s+)(?<geometry1>\()" +
        @"((?<rseparator>\s*|\s*\,{1}\s*|\s+)(?<geometry2>\()" +
        //@"(?<coordlist>(\s*|\s*\,{1}\s*|\s+)\-?(\d*\.?\d+|\d+\.?\d*)([eE][+-]?\d+)?)+" +
        @"((?<separator>\s*|\s*\,{1}\s*|\s+)(?<coordlist>(\-?\d*\.?\d+|\d+\.?\d*)([eE][+-]?\d+)?))+" +
        @"(?<geometry2>\s*\)))+" +
        @"(?<geometry1>\s*\)))+" +
        @"(?<geometry>\s*\))"; //+
        //@"(?<invalid>[^\s]+)"; //put all regex exps here to avoid invalid chars in input string

      getValidationRegex.Add(WKTGeometryType.MultiPolygon, new Regex(pattern, rgOpt));
      getFastRegex.Add(WKTGeometryType.MultiPolygon, getValidationRegex[WKTGeometryType.MultiPolygon]);



      //GeometryCollection regex pattern
      pattern = @"(?<whitespace>\s*)" +
        @"(?<geometryname>" + WKTGeometryType.GeometryCollection.ToString() + @")" +
        @"(?<geometry>\s*\()" +

        @"((?<gseparator>\s*|\s*\,{1}\s*|\s+)" +

        //point, linestring, same regex, only name differs
        @"(?<geometryname>\s*" + WKTGeometryType.Point.ToString() + @"|\s*" + 
        WKTGeometryType.LineString.ToString() + ")" +
        @"(?<geometry1>\s*\()" + //cordlist
        //@"(?<coordlist>(\s*|\s+)\-?(\d*\.?\d+|\d+\.?\d*)([eE][+-]?\d+)?){2}" +
        @"((?<separator>\s*|\s*\,{1}\s*|\s+)(?<coordlist>(\-?\d*\.?\d+|\d+\.?\d*)([eE][+-]?\d+)?))+" +
        @"(?<geometry1>\s*\))" + //cordlist end

        @"|" +

        //polygon
        @"(?<geometryname>\s*" + WKTGeometryType.Polygon.ToString() + @")" +
        @"(?<geometry1>\s*\()" +
        @"((?<rseparator>\s*|\s*\,{1}\s*|\s+)(?<geometry2>\()" +
        //@"(?<coordlist>(\s*|\s*\,{1}\s*|\s+)\-?(\d*\.?\d+|\d+\.?\d*)([eE][+-]?\d+)?)+" +
        @"((?<separator>\s*|\s*\,{1}\s*|\s+)(?<coordlist>(\-?\d*\.?\d+|\d+\.?\d*)([eE][+-]?\d+)?))+" +
        @"(?<geometry2>\s*\)))+" +
        @"(?<geometry1>\s*\))" +

        @")+" +

        @"(?<geometry>\s*\))"; // +
      //@"(?<invalid>[^\s]+)"; //put all regex exps here to avoid invalid chars in input string

      getValidationRegex.Add(WKTGeometryType.GeometryCollection, new Regex(pattern, rgOpt));
      getFastRegex.Add(WKTGeometryType.GeometryCollection, getValidationRegex[WKTGeometryType.GeometryCollection]);

    }



  }

}
